/*****************************************************************************
*    Copyright (C)2003 Ali Corporation. All Rights Reserved.
*
*    File:    nim_tua6120.c
*
*    Description:    This file contains TUA6120 basic function in LLD.
*    History:
*           Date            Athor        Version          Reason
*	    ============	=============	=========	=================
*	1.  17.06.2004		Hao Huang		 Ver 0.1	Create file.
*****************************************************************************/

#include <sys_config.h>
#include <retcode.h>
#include <types.h>

#include <api/libc/printf.h>
#include <bus/i2c/i2c.h>
#include <osal/osal_task.h>
#include "nim_tua6120.h"

/* Tuner device write address */
#define SYS_TUN_TUA6120_WRITE_BASE_ADDR		0xc2

/* Tuner device read address */
#define SYS_TUN_TUA6120_READ_BASE_ADDR		0xc3

struct QPSK_TUNER_CONFIG_EXT* stTUA6120_dev_id[MAX_TUNER_SUPPORT_NUM] = {NULL};
static UINT32 stTUA6120_tuner_cnt = 0;
INT32 nim_tua6120_init(UINT32* tuner_id, struct QPSK_TUNER_CONFIG_EXT * ptrTuner_Config)
{
	struct QPSK_TUNER_CONFIG_EXT* stTUA6120_ptr = NULL;
	if(ptrTuner_Config!=NULL||stTUA6120_tuner_cnt>=MAX_TUNER_SUPPORT_NUM)
		return ERR_FAILUE;
	stTUA6120_ptr = (struct QPSK_TUNER_CONFIG_EXT*)MALLOC(sizeof(struct QPSK_TUNER_CONFIG_EXT));
	if(!stTUA6120_ptr)
		return ERR_FAILUE;
	stTUA6120_dev_id[stTUA6120_tuner_cnt] = stTUA6120_ptr;
	MEMCPY(stTUA6120_ptr, ptrTuner_Config, sizeof(struct QPSK_TUNER_CONFIG_EXT));
	*tuner_id = stTUA6120_tuner_cnt;
	stTUA6120_tuner_cnt++;
	return RET_SUCCESS;
}
/*****************************************************************************
* INT32 tua6120_read(UINT8 reg,UINT8* buff,UINT8 len)
*
* Tuner read register from TUA6120
*
* Arguments:
*  Parameter1: UINT8 reg		: Register offset of TUA6120
*									only use 0x80 ,0x82
*  Parameter2: UINT8* buff		: Read data buffer
*  Parameter3: UINT8 len		: Read length
*
* Return Value: INT32			: Result
*****************************************************************************/
INT32 tua6120_read(UINT32 i2c_type_id, UINT8 base_addr, UINT8 reg,UINT8* buff,UINT8 len)
{
	buff[0] = reg;
	return i2c_write_read(i2c_type_id, base_addr, buff, 1, len);
}

/*****************************************************************************
* INT32 tua6120_write(UINT8 reg,UINT8* buff,UINT8 len)
*
* Tuner write register from TUA6120
*
* Arguments:
*  Parameter1: UINT8 reg		: Register offset of TUA6120
*									0x00 - 0x06
*  Parameter2: UINT8* buff		: write data buffer
*  Parameter3: UINT8 len		: write length
*
* Return Value: INT32			: Result
*****************************************************************************/
INT32 tua6120_write(UINT32 i2c_type_id, UINT8 base_addr, UINT8 reg,UINT8* buff,UINT8 len)
{
	UINT8  i, buffer[8];

	//the max of len is 3
	if (len > 3 )
	{
	    return ERR_FAILUE;
	}

	//add the reg address
	buffer[0] = reg;
	for (i = 0; i < len; i++)
	{
	    buffer[i + 1] = buff[i];
	}

	return i2c_write(i2c_type_id, base_addr, buffer, len + 1);

}


void nim_tua6120_set_VCO( UINT32 freq, UINT8* SV, UINT8* GV, UINT8* GN, UINT8* GR )
{
	if( ( 915 <= freq ) && ( freq < 935) )
	{
		*SV = 1;
		*GV = 0;
		*GN = 1;
		*GR = 7;
	}
	else if( ( 935 <= freq ) && ( freq < 1000) )
	{
		*SV = 0;
		*GV = 0;
		*GN = 1;
		*GR = 6;
	}
	else if( ( 1000 <= freq ) && ( freq < 1080) )
	{
		*SV = 1;
		*GV = 0;
		*GN = 1;
		*GR = 6;
	}
	else if( ( 1080 <= freq ) && ( freq < 1167) )
	{
		*SV = 0;
		*GV = 0;
		*GN = 1;
		*GR = 5;
	}
	else if( ( 1167 <= freq ) && ( freq < 1255) )
	{
		*SV = 1;
		*GV = 0;
		*GN = 1;
		*GR = 5;
	}
	else if( ( 1255 <= freq ) && ( freq < 1313) )
	{
		*SV = 0;
		*GV = 0;
		*GN = 2;
		*GR = 7;
	}
	else if( ( 1313 <= freq ) && ( freq < 1415) )
	{
		*SV = 1;
		*GV = 0;
		*GN = 2;
		*GR = 7;
	}
	else if( ( 1415 <= freq ) && ( freq < 1500) )
	{
		*SV = 0;
		*GV = 0;
		*GN = 2;
		*GR = 6;
	}
	else if( ( 1500 <= freq ) && ( freq < 1615) )
	{
		*SV = 1;
		*GV = 1;
		*GN = 2;
		*GR = 6;
	}
	else if( ( 1615 <= freq ) && ( freq < 1750) )
	{
		*SV = 0;
		*GV = 1;
		*GN = 2;
		*GR = 5;
	}
	else if( ( 1750 <= freq ) && ( freq < 1885) )
	{
		*SV = 1;
		*GV = 1;
		*GN = 2;
		*GR = 5;
	}
	else if( ( 1885 <= freq ) && ( freq < 2000) )
	{
		*SV = 0;
		*GV = 1;
		*GN = 3;
		*GR = 6;
	}
	else if( ( 2000 <= freq ) && ( freq < 2155) )
	{
		*SV = 1;
		*GV = 1;
		*GN = 3;
		*GR = 6;
	}
	else if( ( 2155 <= freq ) && ( freq < 2185) )
	{
		*SV = 0;
		*GV = 1;
		*GN = 3;
		*GR = 5;
	}
	else
	{
		PRINTF("BIG error in nim_tua6120_set_VCO \n");
	}

}


/*****************************************************************************
* INT32 nim_tua6120_control(UINT32 freq, UINT8 bs, UINT8 cp)
*
* Tuner write operation
*
* Arguments:
*  Parameter1: UINT32 freq		: Synthesiser programmable divider
*  Parameter2: UINT8 bs			: Baseband path select
*  Parameter3: UINT8 cp			: Charge pump current
*
* Return Value: INT32			: Result
*****************************************************************************/
INT32 nim_tua6120_control(UINT32 tuner_id, UINT32 freq , UINT32 sym )
{

	UINT8 data[3],i,SV,GV,GHzNcounter, GHzRcounter;
	UINT16 divider;
	UINT32 vcofrq;
	UINT8  N,A;
	INT32  err;
	struct QPSK_TUNER_CONFIG_EXT* stTUA6120_ptr = NULL;
	if(tuner_id>=stTUA6120_tuner_cnt||tuner_id>=MAX_TUNER_SUPPORT_NUM)
		return ERR_FAILUE;
	stTUA6120_ptr = stTUA6120_dev_id[tuner_id];
	PRINTF("Enter nim_tua6120_control freq is %d\n",freq);
	// fRF = [(P*N) + A]*fref/R
	//if fref = 4MHz, so R = 8, and fref/R = 500KHz
	//p = 32
	//so if fRF = 950MHz, N = 59, and A = 12
	//so if fRF = 951MHz, N = 59, and A = 14
	//......
	// if fRF = 2150MHz ,N = 134, and A = 12
	// N = (fRF*2)/32; and A= (fRF*2)%32;

	nim_tua6120_set_VCO( freq , &SV, &GV, &GHzNcounter, &GHzRcounter );

	//Register 00
	MEMSET( data, 0, sizeof(data) );
	data[0] |= 0x80;
	data[0] |= (UINT8)(GV<<6);
	data[0] |= (UINT8)(SV<<5);
	data[0] |= (UINT8)(GHzNcounter<<2);
	//the max value of N is 134 < 256, D17 and D16 is always 0
	N = (freq*2)/32;
	A = (freq*2)%32;
	data[1] |= (UINT8)(N>>1);
	data[2] |= (UINT8)((N&0x01)<<7);
	data[2] |= (UINT8)A;

	PRINTF("REG 0x00 is 0x%x, 0x%x, 0x%x\n",
						data[0], data[1], data[2] );
	err = tua6120_write(stTUA6120_ptr->i2c_type_id, stTUA6120_ptr->cTuner_Base_Addr, 0x00, data, 3 );
	PRINTF("err is 0x%x\n", err );

	//Register 01
	MEMSET( data, 0, sizeof(data) );
	data[0] |= 0x80;
	data[0] |= 0x60;
	data[0] |= (UINT8)(GHzRcounter<<2);
	//R = 8 so R9 and R8 = 0
	data[1] |= 0x08;
	PRINTF("REG 0x01 is 0x%x, 0x%x\n",
						data[0], data[1] );
	err = tua6120_write(stTUA6120_ptr->i2c_type_id, stTUA6120_ptr->cTuner_Base_Addr, 0x01, data, 2 );
	PRINTF("err is 0x%x\n", err );

	//Register 02
	MEMSET( data, 0, sizeof(data) );
	data[0] |= 0x08;
	data[1] |= 0x34;
	PRINTF("REG 0x02 is 0x%x, 0x%x\n",
						data[0], data[1] );
	err = tua6120_write(stTUA6120_ptr->i2c_type_id, stTUA6120_ptr->cTuner_Base_Addr,  0x02, data, 2 );
	PRINTF("err is 0x%x\n", err );

	//Register 03
	MEMSET( data, 0, sizeof(data) );
	data[0] |= 0x00;
	PRINTF("REG 0x03 is 0x%x\n",
						data[0] );
	err = tua6120_write(stTUA6120_ptr->i2c_type_id, stTUA6120_ptr->cTuner_Base_Addr, 0x03, data, 1 );
	PRINTF("err is 0x%x\n", err );

	//Register 04
	MEMSET( data, 0, sizeof(data) );
	data[0] |= 0x38;
	PRINTF("REG 0x04 is 0x%x\n",
						data[0] );
	err = tua6120_write(stTUA6120_ptr->i2c_type_id, stTUA6120_ptr->cTuner_Base_Addr, 0x04, data, 1 );
	PRINTF("err is 0x%x\n", err );

	//Register 05
	MEMSET( data, 0, sizeof(data) );
	if( 11000 >= sym )
	{
		data[0] |= 0x20;
	}
	else if( (11000 < sym )&& ( 22000 >= sym) )
	{
		data[0] |= 0x60;
	}
	else if( (22000 < sym )&& ( 33000 >= sym) )
	{
		data[0] |= 0x40;
	}
	else
	{
		data[0] |= 0x00;
	}
	data[0] |= 0x04;
	PRINTF("REG 0x05 is 0x%x\n",
						data[0] );
	err = tua6120_write(stTUA6120_ptr->i2c_type_id, stTUA6120_ptr->cTuner_Base_Addr, 0x05, data, 1 );
	PRINTF("err is 0x%x\n", err );

	//Register 06
	MEMSET( data, 0, sizeof(data) );
	data[0] |= 0x22;
	PRINTF("REG 0x06 is 0x%x\n",
						data[0] );
	err = tua6120_write(stTUA6120_ptr->i2c_type_id, stTUA6120_ptr->cTuner_Base_Addr, 0x06, data, 1 );
	PRINTF("err is 0x%x\n", err );

	return SUCCESS;
}

/*****************************************************************************
* INT32 nim_tua6120_status(UINT8 *lock)
*
* Tuner read operation
*
* Arguments:
*  Parameter1: UINT8 *lock		: Phase lock status
*
* Return Value: INT32			: Result
*****************************************************************************/
INT32 nim_tua6120_status(UINT32 tuner_id, UINT8 *lock)
{
	UINT8  data;
	INT32  err;
	struct QPSK_TUNER_CONFIG_EXT* stTUA6120_ptr = NULL;
	if(tuner_id>=stTUA6120_tuner_cnt||tuner_id>=MAX_TUNER_SUPPORT_NUM)
	{
		*lock =0;
		return ERR_FAILUE;
	}
	stTUA6120_ptr = stTUA6120_dev_id[tuner_id];
	PRINTF("Enter nim_tua6120_status \n");
	err = tua6120_read(stTUA6120_ptr->i2c_type_id, stTUA6120_ptr->cTuner_Base_Addr, 0x80, &data, 1 );
	PRINTF("err is 0x%x\n", err );
	PRINTF("data is 0x%x\n", data );
	*lock = (UINT8)((data&0x40)>>6);
	PRINTF("Tuner lock is %d\n", *lock );
	return SUCCESS;
}

